#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>

#define BLUE          	"\033[0;32;24m"
#define RED             "\033[0;31;24m"
#define DEPBLUE         "\033[0;34;24m"
#define NONE            "\033[0m"

#define CLEAR()         printf("\033[2j")
#define HIGH_LIGHT      printf("\033[7m")
#define UN_HIGH_LIGHT   printf("\033[27m")
#define RESET           printf(NONE)
#define MOVETO(x,y)     printf("\033[%d;%dH",(y),(x))
 
#define HEIGHT 20
#define WIDETH 40

typedef enum MOVE_DIR {UP = -1,DOWN = 1,LEFT = 2,RIGHT = 4}DIR;
enum MOVE_DIR cur_dir = RIGHT;
int score = 0;
int flag = 0;
int temp = 1;
int snakelength = 3;

typedef struct snake_node{
	int x;
	int y;
	enum MOVE_DIR dir;
	struct snake_node* next;
}snake;

typedef struct food_node{
	int x;
	int y;
//	int color;
//	int time;
	struct food_node* next;
}food;

struct food_node food1,food2;
struct snake_node *head;

int draw_food()
{
	srand(time(NULL));
	food1.x = rand()%38 + 21;
	food1.y = rand()%19 + 6;
}

void draw_randfood()
{
	int god = rand()%3;
	if(!god)
	{
		food2.x = rand()%38 + 21;
		food2.y = rand()%19 + 6;
		MOVETO(food2.x,food2.y);
		printf("☠");
	}
}

void area()
{
	int i;
	MOVETO(20,5);
	printf("┏");
	for(i=0;i<WIDETH-2;i++)
		printf("━");
	printf("┓");
	for(i=1;i<HEIGHT;i++)
	{
		MOVETO(20,5+i);
		printf("┃");
		MOVETO(20+WIDETH-1,5+i);
		printf("┃");
	}
	MOVETO(20,5+HEIGHT);
	printf("┗");
	for(i=0;i<WIDETH-2;i++)
		printf("━");
	printf("┛");
	MOVETO(food1.x,food1.y);
	printf("♟");
}

struct snake_node *creat_link(int n)
{
	struct snake_node *p,*ptail;
	int i;
	for(i=0;i<n;i++)
	{
		p = (struct snake_node *)malloc(sizeof(struct snake_node));
		if(p == NULL)
		{
			free(head);
			printf("failure\n");
			return NULL;
		}
		p->x = 30+i;
		p->y = 15;
		p->dir = RIGHT;
		if(i == 0)
			head = p;
		else
			ptail->next = p;
		ptail = p;
		p->next = NULL;
	}
}

int snake_move(struct snake_node *head)
{
	struct snake_node *pnew,*pold,*p = head,q;
	while(p!= NULL && p->next!=NULL)
		p = p->next;

	if(cur_dir == RIGHT || cur_dir == LEFT)
	{
		q.x = p->x + (cur_dir-3);
		q.y = p->y;
	}
	else
	{
		q.x = p->x;
		q.y = p->y + cur_dir;
	}

	if(q.x > WIDETH+20-2 || q.x < 21)
		flag=1;
	else if(q.y > HEIGHT+5-1 || q.y < 6)
		flag=1;
	p = head;
	while( p->next !=NULL )
	{
			if(q.x == p->x && q.y == p->y)
			flag  = 1;
		p = p->next;
	}

	p = head;
	if(q.x == )
	if(q.x == food1.x && q.y == food1.y)
	{
		score++;
		snakelength++;
		food1.x = rand()%38 + 21;
		food1.y = rand()%19 + 6;

		while(p != NULL)
		{
			if(food1.x == p->x && food1.y == p->y)
			{
				food1.x = rand()%38 + 21;
				food1.y = rand()%19 + 6;
				p = head;
			}
			else
				p = p->next;
		}
		MOVETO(food1.x,food1.y);
		printf("♟");

		pnew = (struct snake_node *)malloc(sizeof(struct snake_node));
		pnew->x = q.x;
		pnew->y = q.y;
		pnew->dir = cur_dir;
		p = head;
		while(p!=NULL)
		{
			pold = p;
			p = p->next;
		}
		pold->next = pnew;
		pnew->next = p;
	}
	else if(q.x == food2.x && q.y == food2.y)
	{
		score = score+5;
		snakelength++;
		int god = rand()%3;
		if(!god)
		{
			food2.x = rand()%38 + 21;
			food2.y = rand()%19 + 6;
			while(p != NULL)
			{
				if(food2.x == p->x && food2.y == p->y)
				{
					food2.x = rand()%38 + 21;
					food2.y = rand()%19 + 6;
					p = head;
				}
				else
					p = p->next;
			}
		MOVETO(food2.x,food2.y);
		printf("☠");
		}

		pnew = (struct snake_node *)malloc(sizeof(struct snake_node));
		pnew->x = q.x;
		pnew->y = q.y;
		pnew->dir = cur_dir;
		p = head;
		while(p!=NULL)
		{
			pold = p;
			p = p->next;
		}
		pold->next = pnew;
		pnew->next = p;
	}
	else
	{
		while(p!= NULL && p->next!=NULL)
		{
			p->x = p->next->x;
			p->y = p->next->y;
			p->dir = p->next->dir;

			p = p->next;
		}
		if(cur_dir == RIGHT || cur_dir == LEFT)
			p->x += (cur_dir-3);
		else
			p->y += cur_dir;
		p->dir = cur_dir;
	}
}

int draw_snake(struct snake_node *head)
{
	int x,y;
	struct snake_node *p = head;
	while(p->next!=NULL)
	{
		MOVETO(p->x,p->y);
		printf("✦");
		p=p->next;
		MOVETO(p->x,p->y);
		switch(p->dir)
		{
			case RIGHT:printf("♚");break;
			case LEFT:printf("♚");break;
			case UP:printf("♚");break;
			case DOWN:printf("♚");break;
		}
		printf("\n");
	}
}

int keyboard()
{
	struct termios oldt,newt;
	int ch;
	int oldf;
	tcgetattr(STDIN_FILENO,&oldt);
	newt = oldt;
	newt.c_lflag &= ~(ICANON | ECHO);
	tcsetattr(STDIN_FILENO,TCSANOW,&newt);
	oldf = fcntl(STDIN_FILENO,F_GETFL,0);
	fcntl(STDIN_FILENO,F_SETFL, oldf | O_NONBLOCK);

	ch =getchar();

	tcsetattr(STDIN_FILENO,TCSANOW,&oldt);
	fcntl(STDIN_FILENO,F_SETFL,&oldf);

	if(ch != EOF)
		return ch;
	else
		return 0;
}

int main()
{
	int n=3;
	int t = 0,time;
	char ch;
	creat_link(n);
	draw_food();
	while(1)
	{
		switch(keyboard())
		{
			case 'w':cur_dir = UP;break;
			case 's':cur_dir = DOWN;break;
			case 'a':cur_dir = LEFT;break;
			case 'd':cur_dir = RIGHT;break;
			case 'f':t = 2;time = 5;break;
			case ' ':temp = !temp;break;
		}
		area();
		snake_move(head);
		MOVETO(1,26);
		printf("%d",score);
		MOVETO(1,28);
		printf("%d",snakelength);
		if(flag)
			return 0;
		draw_snake(head);
		if(time == 0)
		t = 0;
		time--;
		usleep(1000000/(score/5+1+t));
		system("clear");
	}

	return 0;
}